﻿using System.Text;
using System.Text.RegularExpressions;

namespace PmSoft.Core.Extensions;

/// <summary>
/// 字符串类型的扩展方法
/// </summary>
public static class StringExtensions
{
	/// <summary>
	/// 判断字符串是否为 null 或空
	/// </summary>
	/// <param name="value">要判断的字符串</param>
	/// <returns>如果为 null 或空，则为 true；否则为 false</returns>
	public static bool IsNullOrEmpty(this string? value)
	{
		return string.IsNullOrWhiteSpace(value);
	}

	/// <summary>
	/// 将字符串按指定字符分割并转换为数组
	/// </summary>
	/// <typeparam name="T">目标类型</typeparam>
	/// <param name="value">要分割的字符串</param>
	/// <param name="splitChars">分割字符</param>
	/// <returns>转换后的数组</returns>
	public static T?[] ToArray<T>(this string value, string splitChars = ",，;；")
	{
		if (value.IsNullOrEmpty()) return Array.Empty<T>();

		return value
			.Split(splitChars.ToCharArray(), StringSplitOptions.RemoveEmptyEntries)
			.Select(x => x.ConvertTo<T>())
			.ToArray();
	}

	/// <summary>
	/// 将字符串转换为 PascalCase 格式
	/// </summary>
	/// <param name="str">要转换的字符串</param>
	/// <returns>转换后的字符串</returns>
	public static string ToPascalCase(this string str)
	{
		IList<char> list = new List<char>();
		if (str.Length > 0)
		{
			list.Add(char.ToUpper(str[0]));
		}
		for (var i = 1; i < str.Length; i++)
		{
			if (char.IsWhiteSpace(str[i]) || str[i] == '_') continue;
			if (char.IsWhiteSpace(str[i - 1]) || str[i - 1] == '_')
			{
				list.Add(char.ToUpper(str[i]));
			}
			else
			{
				list.Add(char.ToLower(str[i]));
			}
		}
		return new string(list.ToArray());
	}

	/// <summary>
	/// 将字符串转换为 CamelCase 格式
	/// </summary>
	/// <param name="value">要转换的字符串</param>
	/// <returns>转换后的字符串</returns>
	public static string ToCamelCase(this string value)
	{
		if (value.IsNullOrEmpty() || !char.IsUpper(value[0]))
		{
			return value;
		}

		var chars = value.ToCharArray();

		for (var i = 0; i < chars.Length; i++)
		{
			if (i == 1 && !char.IsUpper(chars[i]))
			{
				break;
			}

			var hasNext = i + 1 < chars.Length;
			if (i > 0 && hasNext && !char.IsUpper(chars[i + 1]))
			{
				if (char.IsSeparator(chars[i + 1]))
				{
					chars[i] = char.ToLowerInvariant(chars[i]);
				}

				break;
			}

			chars[i] = char.ToLowerInvariant(chars[i]);
		}

		return new string(chars);
	}

	/// <summary>
	/// 将字符串转换为 SnakeCase 格式
	/// </summary>
	/// <param name="value">要转换的字符串</param>
	/// <returns>转换后的字符串</returns>
	public static string ToSnakeCase(this string value)
	{
		if (string.IsNullOrEmpty(value))
		{
			return value;
		}

		var sb = new StringBuilder();
		var state = SnakeCaseState.Start;

		for (var i = 0; i < value.Length; i++)
		{
			if (value[i] == ' ')
			{
				if (state != SnakeCaseState.Start)
				{
					state = SnakeCaseState.NewWord;
				}
			}
			else if (char.IsUpper(value[i]))
			{
				switch (state)
				{
					case SnakeCaseState.Upper:
						var hasNext = i + 1 < value.Length;
						if (i > 0 && hasNext)
						{
							var nextChar = value[i + 1];
							if (!char.IsUpper(nextChar) && nextChar != '_')
							{
								sb.Append('_');
							}
						}
						break;

					case SnakeCaseState.Lower:
					case SnakeCaseState.NewWord:
						sb.Append('_');
						break;
				}

				sb.Append(char.ToLowerInvariant(value[i]));

				state = SnakeCaseState.Upper;
			}
			else if (value[i] == '_')
			{
				sb.Append('_');
				state = SnakeCaseState.Start;
			}
			else
			{
				if (state == SnakeCaseState.NewWord)
				{
					sb.Append('_');
				}

				sb.Append(value[i]);
				state = SnakeCaseState.Lower;
			}
		}

		return sb.ToString();
	}

	/// <summary>
	/// 将 Base64 字符串转换为字节数组
	/// </summary>
	/// <param name="value">Base64 字符串</param>
	/// <returns>字节数组</returns>
	public static byte[] FromBase64(this string value)
	{
		return Convert.FromBase64String(value);
	}

	/// <summary>
	/// 将十六进制字符串转换为字节数组
	/// </summary>
	/// <param name="value">十六进制字符串</param>
	/// <returns>字节数组</returns>
	public static byte[] FromHex(this string value)
	{
		value = value.StartsWith("0x", StringComparison.Ordinal) ? value[2..] : value;
		return Convert.FromHexString(value);
	}

	/// <summary>
	/// 将字符串转换为字节数组
	/// </summary>
	/// <param name="value">要转换的字符串</param>
	/// <param name="charSet">字符集</param>
	/// <returns>字节数组</returns>
	public static byte[] ToBytes(this string value, string charSet = "utf-8")
	{
		try
		{
			return Encoding.GetEncoding(charSet).GetBytes(value);
		}
		catch
		{
			return Encoding.UTF8.GetBytes(value);
		}
	}

	/// <summary>
	/// 将字符串格式化为单行
	/// </summary>
	/// <param name="text">要格式化的字符串</param>
	/// <returns>格式化后的字符串</returns>
	public static string ToSingleLine(this string text)
	{
		if (string.IsNullOrEmpty(text))
			return text;
		return Regex.Replace(text, "[\f\n\r\t\v]", "");
	}

	/// <summary>
	/// 查找匹配的括号
	/// </summary>
	/// <param name="format">格式字符串</param>
	/// <param name="startIndex">起始索引</param>
	/// <returns>匹配的括号索引</returns>
	public static int FindMatchingBrace(string format, int startIndex)
	{
		int depth = 1;
		for (int i = startIndex + 1; i < format.Length; i++)
		{
			if (format[i] == '{')
			{
				depth++;
			}
			else if (format[i] == '}')
			{
				depth--;
				if (depth == 0)
				{
					return i;
				}
			}
		}

		return -1;
	}

	/// <summary>
	/// 表示 SnakeCase 的状态
	/// </summary>
	private enum SnakeCaseState
	{
		Start,
		Lower,
		Upper,
		NewWord
	}
}



